package com.yinhai.ta404.component.org.sysmg.resource.service.read.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yinhai.ta404.component.org.core.constant.OrgConstant;
import com.yinhai.ta404.component.org.core.entity.TaRoleRestPo;
import com.yinhai.ta404.component.org.core.service.impl.OrgBaseService;
import com.yinhai.ta404.component.org.core.vo.TaResourceVo;
import com.yinhai.ta404.component.org.sysmg.resource.entity.TaResourcePo;
import com.yinhai.ta404.component.org.sysmg.resource.entity.TaResourceRestUrlPo;
import com.yinhai.ta404.component.org.sysmg.resource.mapper.read.ResourceOverlayReadMapper;
import com.yinhai.ta404.component.org.sysmg.resource.mapper.read.ResourceReadMapper;
import com.yinhai.ta404.component.org.sysmg.resource.mapper.read.RestUrlReadMapper;
import com.yinhai.ta404.component.org.sysmg.resource.service.read.ResourceReadService;
import com.yinhai.ta404.component.org.sysmg.resource.service.write.impl.ResourceWriteServiceImpl;
import com.yinhai.ta404.component.org.sysmg.resource.vo.TaResourceParamVo;
import com.yinhai.ta404.component.org.sysmg.system.entity.TaAccessSystemPo;
import com.yinhai.ta404.component.org.sysmg.system.mapper.read.AccessSystemReadMapper;
import com.yinhai.ta404.component.org.sysmg.system.vo.TaAccessSystemVo;
import com.yinhai.ta404.core.exception.AppException;
import com.yinhai.ta404.core.security.service.ITaResourceReadService;
import com.yinhai.ta404.core.security.vo.BaseResourceVo;
import com.yinhai.ta404.core.security.vo.BaseRoleVo;
import com.yinhai.ta404.core.security.vo.RestUrlVo;
import com.yinhai.ta404.core.security.vo.UserAccountVo;
import com.yinhai.ta404.core.transaction.annotation.TaTransactional;
import com.yinhai.ta404.core.utils.JsonFactory;
import com.yinhai.ta404.core.utils.ObjectConversionUtil;
import com.yinhai.ta404.core.utils.ValidateUtil;
import com.yinhai.ta404.module.dict.DictConstants;
import com.yinhai.ta404.module.dict.entity.TaDictPo;
import com.yinhai.ta404.module.dict.util.DictUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.yinhai.ta404.component.org.core.constant.OrgConstant.*;
import static com.yinhai.ta404.core.IConstants.NO;
import static com.yinhai.ta404.core.IConstants.YES;


@Service
@TaTransactional(readOnly = true)
public class ResourceReadServiceImpl extends OrgBaseService implements ITaResourceReadService, ResourceReadService {
    private static final Logger logger = LoggerFactory.getLogger(ResourceReadServiceImpl.class);

    @Resource
	ResourceReadMapper resourceReadMapper;

    @Resource
	ResourceOverlayReadMapper resourceOverlayReadMapper;

    @Resource
	AccessSystemReadMapper accessSystemReadMapper;

    @Resource
	RestUrlReadMapper restUrlReadMapper;


    @Override
    public List<TaResourceVo> queryResourceByParam(TaResourceParamVo resourceParamVo) {
        return resourceParamVo.isEmpty()
                ? queryNextLevelResourceWithSelf(rootConfig.getResourceRootId())
                : poListToVoList(addRestUrl(resourceReadMapper.queryByCondition(resourceParamVo.toPo()).stream()
                .filter(po ->
                        !rootConfig.getWorkbenchParentId().equals(po.getResourceId())
                                && (!rootConfig.getWorkbenchParentId().equals(po.getpResourceId()))
                                && (!OrgConstant.YES.equals(po.getWorkbench()))
                )
                .filter(vo -> !OrgConstant.RESOURCE_AUDITOR_MENU.equals(vo.getResourceType()) && !OrgConstant.RESOURCE_EXAMINER_MENU.equals(vo.getResourceType()))
                .collect(Collectors.toList()), restUrlReadMapper.queryAllRestUrl()));
    }

    @Override
    public TaResourceVo toEditOrAdd(String resourceId, String operationType) {
        if (ValidateUtil.isEmpty(resourceId)) {
            resourceId = rootConfig.getResourceRootId();
        }
        if (RESOURCE_OPERATION_TYPE_ADD.equals(operationType)) {
            TaResourceVo taResourceVo = new TaResourceVo();
            TaResourceVo tmp = queryResource(resourceId);
            if (ValidateUtil.isEmpty(tmp)) {
                throw new AppException("该功能资源已删除,无法新增下级功能资源！");
            }
            taResourceVo.setpResourceId(tmp.getResourceId());
            taResourceVo.setpResourceName(tmp.getName());
            Integer sortNo = resourceReadMapper.queryNextLevelMaxOrderNo(resourceId);
            if (ValidateUtil.isEmpty(sortNo)) {
                sortNo = MIN_ORDERNO;
            } else {
                sortNo += ORDERNO_INTERVAL;
            }
            taResourceVo.setOrderNo(sortNo);
            return taResourceVo;
        }
        if (RESOURCE_OPERATION_TYPE_EDIT.equals(operationType)) {
            return queryResource(resourceId);
        }
        if (logger.isWarnEnabled()) {
            logger.warn("功能资源操作类型{}越界，无法找到该操作内容！", operationType);
        }
        throw new AppException("操作类型越界，无法找到该操作内容！请联系系统管理员！");
    }

    @Override
    public TaResourceVo queryResource(String resourceId) {
        if (ValidateUtil.isEmpty(resourceId)) {
            throw new AppException("功能资源唯一标识为空，无法查询详细信息！");
        }
        List<TaResourcePo> resourcePoList = new ArrayList<>();
        resourcePoList.add(resourceReadMapper.get(resourceId));
        return addRestUrl(resourcePoList, restUrlReadMapper.queryRestUrlByResourceId(resourceId)).get(0).toVo();
    }

    @Override
    public List<TaResourceVo> queryAllResources() {
        List<TaResourcePo> taResourcePoList = resourceReadMapper.queryAll();
        taResourcePoList = taResourcePoList.stream().filter(resourcePo -> YES.equals(resourcePo.getEffective())).collect(Collectors.toList());
        if (ValidateUtil.isEmpty(taResourcePoList) || taResourcePoList.isEmpty()) {
            return new ArrayList<>();
        }
        return poListToVoList(taResourcePoList);
    }

    @Override
    public List<TaResourceVo> queryEffectiveResources(String userId) {
        List<BaseRoleVo> roleVos = queryEnableRoleByUserId(userId, getSysTimestamp());
        return queryResourceByUserIdAndRole(userId, roleVos);
    }

    @Override
    public List<TaResourceVo> queryResourceByUserId(UserAccountVo userAccountVo) {
        if (null == userAccountVo) {
            logger.info("queryResourceByUserId start null");
            return queryResourceByUserIdAndRole(null, null);
        }

        logger.info("queryResourceByUserId start not null");
        return queryResourceByUserIdAndRole(userAccountVo.getUserId(), userAccountVo.getRoles());
    }

    private List<TaResourceVo> queryResourceByUserIdAndRole(String userId, List<BaseRoleVo> roleVos) {
        Set<String> roleTypeSet = new HashSet<>(4);
        if (ValidateUtil.isNotEmpty(roleVos)) {
            roleVos.forEach(vo -> roleTypeSet.add(vo.getRoleType()));
        }

        List<TaResourcePo> vosTmp = new ArrayList<>();

        logger.info("queryResourceByUserId start queryBySecurityPolicy");

        vosTmp.addAll(resourceReadMapper.queryBySecurityPolicy(RESOURCE_SECURITYPOLICY_LOGIN_ACCESS, YES));
        vosTmp.addAll(resourceReadMapper.queryBySecurityPolicy(RESOURCE_SECURITYPOLICY_NOLOGIN_ACCESS, YES));


        logger.info("queryResourceByUserId start queryByResourceType");
        if (roleTypeSet.size() == 1 && roleTypeSet.contains(ROLE_TYPE_AUDITOR)) {

            logger.info("queryResourceByUserId start1 queryByResourceType");
            vosTmp.addAll(resourceReadMapper.queryByResourceType(RESOURCE_AUDITOR_MENU));
        } else if (roleTypeSet.size() == 1 && roleTypeSet.contains(ROLE_TYPE_EXAMINER)) {

            logger.info("queryResourceByUserId start2 queryByResourceType");
            vosTmp.addAll(resourceReadMapper.queryByResourceType(RESOURCE_EXAMINER_MENU));
        } else if (roleTypeSet.contains(ROLE_TYPE_EXAMINER) || roleTypeSet.contains(ROLE_TYPE_AUDITOR)) {
            logger.info("queryResourceByUserId start3 queryByResourceType");
            throw new AppException("当前人员所属角色存在跨三权分立范围角色类型！");
        } else if (ValidateUtil.isNotEmpty(userId)) {
            if (isDeveloper(userId)) {
                logger.info("queryResourceByUserId start4 queryByEffective");
                List<TaResourcePo> pos = resourceReadMapper.queryByEffective(YES);
                vosTmp = pos.stream().filter(vo -> !(RESOURCE_EXAMINER_MENU.equals(vo.getResourceType()) || RESOURCE_AUDITOR_MENU.equals(vo.getResourceType()))).collect(Collectors.toList());
            } else {
                logger.info("queryResourceByUserId start4 queryByUserId");
                vosTmp.addAll(resourceReadMapper.queryByUserId(userId, YES, YES, getSysDate()));
            }
        }
        logger.info("queryResourceByUserId start5 poListToVoList");
        List<TaResourceVo> resourceVos = poListToVoList(vosTmp);
        logger.info("queryResourceByUserId end poListToVoList");

        resourceVos =  resourceVos.stream()
                .collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(TaResourceVo::getResourceId))), ArrayList::new));
        logger.info("resourceVos end");
        return resourceVos;
    }


    @Override
    public List<TaResourceVo> queryChildResources(String resourceId) {
        if (ValidateUtil.isEmpty(resourceId)) {
            throw new AppException("功能资源ID为空，无法获取功能资源！");
        }
        return poListToVoList(resourceReadMapper.queryChild(resourceId));
    }

	@Override
	public Set<String> queryUrlWithResourceIds(Set<String> resourceIds) {
		if (ValidateUtil.isEmpty(resourceIds)) {
			return new HashSet<>();
		}

		return resourceOverlayReadMapper.queryUrlWithResourceIds(resourceIds);
	}


	@Override
	public List<BaseResourceVo> queryIChildResources(String resourceId) {
		if (ValidateUtil.isEmpty(resourceId)) {
            return new ArrayList<>();
		}

		List<TaResourcePo> taResourcePoList = resourceReadMapper.queryChild(resourceId);
		if (Objects.isNull(taResourcePoList) || taResourcePoList.isEmpty()) {
			return new ArrayList<>();
		}
		List<BaseResourceVo> taResourceVos = new ArrayList<>();
		taResourcePoList.forEach(resourcePo -> taResourceVos.add(resourcePo.toVo()));
		return taResourceVos;
	}

    @Override
    public List<TaResourceVo> queryNextLevelResourceWithSelf(String resourceId) {
        resourceId = ValidateUtil.isEmpty(resourceId) ? rootConfig.getOrgRootId() : resourceId;
        return poListToVoList(
                addRestUrl(resourceReadMapper.queryNextLevelChildWithSelf(resourceId).stream()
                        .filter(po ->
                                (!rootConfig.getWorkbenchParentId().equals(po.getResourceId()))
                                        && (!rootConfig.getWorkbenchParentId().equals(po.getpResourceId()))
                                        && (OrgConstant.NO.equals(po.getWorkbench()))
                        )
                        .filter(vo -> !OrgConstant.RESOURCE_AUDITOR_MENU.equals(vo.getResourceType()) && !OrgConstant.RESOURCE_EXAMINER_MENU.equals(vo.getResourceType()))
                        .collect(Collectors.toList()), restUrlReadMapper.queryAllRestUrl()));
    }

    @Override
    public List<TaResourceVo> queryResourceByUrl(String url) {
        return poListToVoList(resourceReadMapper.queryByUrl(url));
    }


    @Override
    public List<BaseResourceVo> queryResourceWithRoleId(String roleId) {
        if (ValidateUtil.isEmpty(roleId)) {
            return new ArrayList<>(0);
        }
        List<TaResourceVo> taResourceVoList = poListToVoList(resourceReadMapper.queryWitRoleId(roleId, YES));
        return new ArrayList<>(taResourceVoList);
    }

    @Override
    public List<BaseResourceVo> queryResourceEffectiveWithRoleId(String roleId) {
        if (ValidateUtil.isEmpty(roleId)) {
            return new ArrayList<>();
        }
        List<TaResourceVo> taResourceVoList = poListToVoList
                (resourceReadMapper.queryEffectiveWithRoleId(roleId, YES, YES, getSysDate()));
        List<BaseResourceVo> baseResourceVoList = new ArrayList<>(taResourceVoList);
        List<TaRoleRestPo> roleRestPoList = super.queryRestAuthorityByRoleId(roleId);
        List<TaResourceRestUrlPo> resourceRestUrlPoList = restUrlReadMapper.queryAllRestUrl();
        List<RestUrlVo> restUrlVoList = resourceRestUrlPoList.stream().map(po -> {
            RestUrlVo restUrlVo = new RestUrlVo(po.getUrlId(), po.getResourceId(), po.getRestUrl(), po.getUrlName(), po.getAuthorityPolicy(), NO);
            roleRestPoList.forEach(roleRestPo -> {
                if (po.getResourceId().equals(roleRestPo.getResourceId())
                        && po.getUrlId().equals(roleRestPo.getUrlId()) && RESOURCE_REST_URL_ALONE.equals(po.getAuthorityPolicy())) {
                    restUrlVo.setChecked(YES);
                }
            });
            return restUrlVo;
        }).collect(Collectors.toList());
        return baseResourceVoList.stream().peek(vo -> {
            if (null == vo.getRestUrlList()) {
                vo.setRestUrlList(new ArrayList<>());
            }
            List<RestUrlVo> restUrlVos = vo.getRestUrlList();
            restUrlVoList.forEach(restVo -> {
                if (restVo.getResourceId().equals(vo.getResourceId())) {
                    restUrlVos.add(restVo);
                }
            });
            vo.setRestUrlList(restUrlVos);
        }).collect(Collectors.toList());
    }

    @Override
    public List<BaseResourceVo> queryResourceEffectiveWithRoleIds(List<String> roleIds) {
        if (ValidateUtil.isEmpty(roleIds) || roleIds.isEmpty()) {
            return new ArrayList<>();
        }
        List<TaResourceVo> taResourceVoList = poListToVoList
                (addRestUrl(resourceReadMapper.queryEffectiveWithRoleIds(roleIds, YES, YES, getSysDate()), restUrlReadMapper.queryAllRestUrl()));
        return new ArrayList<>(taResourceVoList);
    }

    @Override
    public List<BaseResourceVo> queryResourceEffectiveWithUserId(String userId) {
        List<BaseResourceVo> baseResourceVoList = new ArrayList<>();

        baseResourceVoList.addAll(queryResourceLogin().stream().map(vo -> (TaResourceVo) vo).collect(Collectors.toList()));
        baseResourceVoList.addAll(queryResourceNoLogin().stream().map(vo -> (TaResourceVo) vo).collect(Collectors.toList()));

        List<BaseRoleVo> roleVos = queryEnableRoleByUserId(userId, getSysTimestamp());
        Set<String> roleTypeSet = roleVos.stream().map(BaseRoleVo::getRoleType).collect(Collectors.toSet());

        List<TaResourceRestUrlPo> resourceRestUrlPoList = restUrlReadMapper.queryAllRestUrl();

        if (roleTypeSet.size() == 1 && roleTypeSet.contains(ROLE_TYPE_AUDITOR)) {
            baseResourceVoList.addAll(poListToVoList(resourceReadMapper.queryByResourceType(RESOURCE_AUDITOR_MENU)));
            baseResourceVoList = assembleRestUrlPo(baseResourceVoList, resourceRestUrlPoList);
        } else if (roleTypeSet.size() == 1 && roleTypeSet.contains(ROLE_TYPE_EXAMINER)) {
            baseResourceVoList.addAll(poListToVoList(resourceReadMapper.queryByResourceType(RESOURCE_EXAMINER_MENU)));
            baseResourceVoList = assembleRestUrlPo(baseResourceVoList, resourceRestUrlPoList);
        } else if (roleTypeSet.contains(ROLE_TYPE_EXAMINER) || roleTypeSet.contains(ROLE_TYPE_AUDITOR)) {
            throw new AppException("当前人员所属角色存在跨三权分立范围角色类型！");
        } else {
            if (isDeveloper(userId)) {
                List<TaResourceVo> vos = poListToVoList(resourceReadMapper.queryByEffective(YES));
                baseResourceVoList = vos.stream().filter(vo -> !(RESOURCE_EXAMINER_MENU.equals(vo.getResourceType()) || RESOURCE_AUDITOR_MENU.equals(vo.getResourceType()))).collect(Collectors.toList());
                baseResourceVoList = assembleRestUrlPo(baseResourceVoList, resourceRestUrlPoList);
            } else {
                List<TaRoleRestPo> roleRestPoList = super.queryRestAuthorityByUserId(userId);
                List<RestUrlVo> restUrlVoList = resourceRestUrlPoList.stream().map(po -> {
                    RestUrlVo restUrlVo = new RestUrlVo(po.getUrlId(), po.getResourceId(), po.getRestUrl(), po.getUrlName(), po.getAuthorityPolicy(), NO);
                    roleRestPoList.forEach(roleRestPo -> {
                        if (po.getResourceId().equals(roleRestPo.getResourceId())
                                && po.getUrlId().equals(roleRestPo.getUrlId()) && RESOURCE_REST_URL_ALONE.equals(po.getAuthorityPolicy())) {
                            restUrlVo.setChecked(YES);
                        }
                    });
                    return restUrlVo;
                }).collect(Collectors.toList());

                baseResourceVoList.addAll(poListToVoList(resourceReadMapper.queryByUserId(userId, YES, YES, getSysDate())));
                baseResourceVoList = assembleUrl(baseResourceVoList, restUrlVoList);
            }
        }
        return baseResourceVoList;
    }

    private List<BaseResourceVo> assembleUrl(List<BaseResourceVo> resourceVos, List<RestUrlVo> restUrlVos) {
        Map<String, List<RestUrlVo>> map = new HashMap<>(16);
        restUrlVos.forEach(vo -> {
            List<RestUrlVo> list = map.get(vo.getResourceId());
            if (null == list) {
                list = new ArrayList<>();
            }
            list.add(vo);
            map.put(vo.getResourceId(), list);
        });
        return resourceVos.stream().peek(vo -> {
            vo.setRestUrlList(map.get(vo.getResourceId()));
        }).collect(Collectors.toList());
    }

    private List<BaseResourceVo> assembleRestUrlPo(List<BaseResourceVo> resourceVos, List<TaResourceRestUrlPo> pos) {
        Map<String, List<RestUrlVo>> resourceRestUrlPoMap = new HashMap<>(64);
        pos.forEach(po -> {
            List<RestUrlVo> list = resourceRestUrlPoMap.get(po.getResourceId());
            if (null == list) {
                list = new ArrayList<>();
            }
            list.add(new RestUrlVo(po.getUrlId(), po.getResourceId(), po.getRestUrl(), po.getUrlName(), po.getAuthorityPolicy(), YES));
            resourceRestUrlPoMap.put(po.getResourceId(), list);
        });
        return resourceVos.stream().peek(vo -> {
            List<RestUrlVo> list = resourceRestUrlPoMap.get(vo.getResourceId());
            if (null == list) {
                vo.setRestUrlList(new ArrayList<>());
            } else {
                vo.setRestUrlList(list);
            }
        }).collect(Collectors.toList());
    }

    @Override
    public List<BaseResourceVo> queryResourceNoLogin() {
        return getBaseResourceVo(RESOURCE_SECURITYPOLICY_NOLOGIN_ACCESS);
    }

    private List<BaseResourceVo> getBaseResourceVo(String resourceSecurityPolicyNoLoginAccess) {
        List<TaResourceVo> taResourceVoList = poListToVoList(addRestUrl(resourceReadMapper.queryBySecurityPolicy(resourceSecurityPolicyNoLoginAccess, YES), restUrlReadMapper.queryAllRestUrl()));
        return new ArrayList<>(taResourceVoList);
    }

    @Override
    public List<BaseResourceVo> queryResourceLogin() {
        return getBaseResourceVo(RESOURCE_SECURITYPOLICY_LOGIN_ACCESS);
    }

    @Override
    public List<TaAccessSystemVo> queryAllAccessSystem() {
        List<TaAccessSystemVo> taAccessSystemVoList = new ArrayList<>();
        List<TaAccessSystemPo> accessSystemPoList = accessSystemReadMapper.queryAllEffectiveTaAccessSystem(YES);
        accessSystemPoList.forEach(accessSystemPo -> taAccessSystemVoList.add(ObjectConversionUtil.convert(new TaAccessSystemVo(), accessSystemPo)));
        return taAccessSystemVoList;
    }

    @Override
    public Long queryResourceBySysId(String sysId) {
        return resourceReadMapper.queryBySysId(sysId);
    }

    @Override
    public Object exportResource() {
        return null;
    }

    @Override
    public JSONArray queryResourceTypeLimit(String resourceId, String opType) {
        if (ValidateUtil.isEmpty(resourceId)) {
            resourceId = rootConfig.getResourceRootId();
        }
        List<TaDictPo> dictPos = DictUtils.getCodeList(RESOURCE_TYPE_DICT_NAME, DictConstants.DICT_DEFAULT_AUTHORITY);

        if (ValidateUtil.isEmpty(opType)) {
            if (logger.isWarnEnabled()) {
                logger.warn("无法获取操作类型，不对资源类型字典做处理！");
            }
            return getResourceTypeJsonArray(dictPos, true, null);
        }


        if (RESOURCE_OPERATION_TYPE_ADD.equals(opType)) {

            if (rootConfig.getResourceRootId().equals(resourceId)) {
                return getResourceTypeJsonArray(dictPos, true, null);
            }

            TaResourcePo resourcePo = resourceReadMapper.get(resourceId);
            if (ValidateUtil.isEmpty(resourcePo)) {
                if (logger.isWarnEnabled()) {
                    logger.warn("功能资源不存在，不对资源类型字典做处理！");
                }
                return getResourceTypeJsonArray(dictPos, true, null);
            }
            if (RESOURCE_COMMON_MENU.equals(resourcePo.getResourceType())) {
                return getResourceTypeJsonArray(dictPos, true, null);
            }
            return getResourceTypeJsonArray(dictPos, false, Collections.singleton(resourcePo.getResourceType()));
        } else if (RESOURCE_OPERATION_TYPE_EDIT.equals(opType)) {

            if (rootConfig.getResourceRootId().equals(resourceId)) {
                return getResourceTypeJsonArray(dictPos, false, Collections.singleton(RESOURCE_COMMON_MENU));
            }
            TaResourcePo resourcePo = resourceReadMapper.get(resourceId);
            if (ValidateUtil.isEmpty(resourcePo)) {
                if (logger.isWarnEnabled()) {
                    logger.warn("功能资源不存在，不对资源类型字典做处理！");
                }
                return getResourceTypeJsonArray(dictPos, true, null);
            }
            TaResourcePo parentPo = resourceReadMapper.get(resourcePo.getpResourceId());

            if (RESOURCE_COMMON_MENU.equals(resourcePo.getResourceType()) || RESOURCE_COMMON_MENU.equals(parentPo.getResourceType())) {
                List<TaResourcePo> resourcePos = resourceReadMapper.queryChild(resourceId);
                if (ValidateUtil.isEmpty(resourcePos) || resourcePos.size() == 1) {
                    return getResourceTypeJsonArray(dictPos, true, null);
                }
                Set<String> valueSet = new HashSet<>(4);
                String finalResourceId = resourceId;
                resourcePos.forEach(po -> {
                    if (!finalResourceId.equals(po.getResourceId())) {
                        valueSet.add(po.getResourceType());
                    }
                });

                if (valueSet.size() > 1) {
                    return getResourceTypeJsonArray(dictPos, false, Collections.singleton(RESOURCE_COMMON_MENU));
                } else {
                    valueSet.add(RESOURCE_COMMON_MENU);
                    return getResourceTypeJsonArray(dictPos, false, valueSet);
                }
            } else {

                return getResourceTypeJsonArray(dictPos, false, Collections.singleton(parentPo.getResourceType()));
            }
        }
        if (logger.isWarnEnabled()) {
            logger.warn("功能资源操作越界，当前操作类型{}不存在！", opType);
        }
        throw new AppException("操作越界，当前操作类型不存在，操作类型只能为新增(1)或者编辑(2)！");
    }

    private JSONArray getResourceTypeJsonArray(List<TaDictPo> dictPos, boolean editable, Set<String> except) {
        JSONArray resultArr = new JSONArray();
        final String label = "label";
        final String value = "value";
        final String edit = "editable";
        dictPos.forEach(po -> {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(label, po.getLabel());
            jsonObject.put(value, po.getValue());
            if (ValidateUtil.isNotEmpty(except) && except.contains(po.getValue())) {
                jsonObject.put(edit, !editable);
            } else {
                jsonObject.put(edit, editable);
            }
            resultArr.add(jsonObject);
        });
        return resultArr;
    }

    @Override
    public boolean isAloneUiAuthorityPolicy(String resourceId) {
        TaResourcePo resourcePo = resourceReadMapper.get(resourceId);
        if (null == resourcePo) {
            throw new AppException("功能资源不存在，无法访问！");
        }
        return RESOURCE_UI_AUTHORITYPOLICY_ALONE.equals(resourcePo.getUiAuthorityPolicy());
    }

    @Override
    public List<TaResourcePo> queryByUserIdWithField01(String userId, String field01) {
        return resourceOverlayReadMapper.queryByUserIdWithField01(userId, YES, YES, getSysDate(), field01);
    }

    @Override
    public List<TaResourcePo> queryBtn(String field01) {
        return resourceOverlayReadMapper.queryBtn(field01);
    }

    @Override
    public Map<String, Set<RestUrlVo>> queryBtnInfoWithRestUrl(List<String> resourceIdList, List<String> excludeBtnId) {
        List<TaResourcePo> poList = resourceOverlayReadMapper.queryBtn(ResourceWriteServiceImpl.BUTTON_TYPE);
        poList = poList.stream().filter(po -> resourceIdList.contains(po.getpResourceId()) && !excludeBtnId.contains(po.getResourceId())).collect(Collectors.toList());
        List<TaResourceRestUrlPo> resourceRestUrlPoList = restUrlReadMapper.queryAllRestUrl();
        List<RestUrlVo> restUrlVoList = resourceRestUrlPoList.stream().map(po -> new RestUrlVo(po.getUrlId(), po.getResourceId(), po.getRestUrl(), po.getUrlName(), po.getAuthorityPolicy(), NO)).collect(Collectors.toList());
        List<BaseResourceVo> voList = assembleUrl(new ArrayList<>(poListToVoList(poList)), restUrlVoList);

        Map<String, Set<RestUrlVo>> map = new HashMap<>(32);
        voList.forEach(vo -> {
            if(ValidateUtil.isNotEmpty(vo.getRestUrlList())) {
                Set<RestUrlVo> set = map.computeIfAbsent(vo.getpResourceId(), k -> new HashSet<>());
                set.addAll(vo.getRestUrlList());
                map.put(vo.getpResourceId(), set);
            }
        });
        return map;
    }

    private List<TaResourcePo> addRestUrl(List<TaResourcePo> resourcePoList, List<TaResourceRestUrlPo> resourceRestUrlPoList) {
        if (ValidateUtil.isEmpty(resourcePoList) || ValidateUtil.isEmpty(resourceRestUrlPoList)) {
            return resourcePoList;
        }

        Map<String, List<Map<String, Object>>> mapList = new HashMap<>(8);

        resourceRestUrlPoList.forEach(rest -> {
            String resourceId = rest.getResourceId();
            List<Map<String, Object>> restUrlPoList = mapList.get(resourceId);
            ;
            if (null == restUrlPoList) {
                restUrlPoList = new ArrayList<>(2);
            }
            Map<String, Object> map = new HashMap<>(8);
            map.put("resourceId", resourceId);
            map.put("url", rest.getRestUrl());
            map.put("name", rest.getUrlName());
            map.put("authorityPolicy", rest.getAuthorityPolicy());
            map.put("id", rest.getUrlId());
            restUrlPoList.add(map);
            mapList.put(resourceId, restUrlPoList);

        });

        return resourcePoList.stream().peek(po -> po.setRestUrl(JsonFactory.bean2json(mapList.get(po.getResourceId())))).collect(Collectors.toList());
    }


    @Override
    public TaResourcePo queryMenuByMenuId(String resourceId) {
        TaResourcePo resourcePo = resourceReadMapper.get(resourceId);
        if (null == resourcePo) {
            throw new AppException("功能资源不存在，无法访问！");
        }
        return resourcePo;
    }
}
